package com.example.prom.ok.y2023.work.recaptcha;


import com.google.cloud.recaptchaenterprise.v1.RecaptchaEnterpriseServiceClient;
import com.google.protobuf.ByteString;
import com.google.recaptchaenterprise.v1.AccountDefenderAssessment.AccountDefenderLabel;
import com.google.recaptchaenterprise.v1.Assessment;
import com.google.recaptchaenterprise.v1.CreateAssessmentRequest;
import com.google.recaptchaenterprise.v1.Event;
import com.google.recaptchaenterprise.v1.ProjectName;
import com.google.recaptchaenterprise.v1.RiskAnalysis.ClassificationReason;
import com.google.recaptchaenterprise.v1.TokenProperties;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class AccountDefenderAssessment {

    public static void main(String[] args)
            throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        // TODO(developer): Replace these variables before running the sample.
        String projectId = "lanzhizhuxia";
        String recaptchaSiteKey = "6Lee36MkAAAAAO5exxBKI2TJQ9rMpwikPtVCQZ91";

        // token: The token obtained from the client on passing the recaptchaSiteKey.
        // To get the token, integrate the recaptchaSiteKey with frontend. See,
        // https://cloud.google.com/recaptcha-enterprise/docs/instrument-web-pages#frontend_integration_score
        String token = "03AFY_a8Uw01zDsDzfT0gCd1jJLJnMnCCvIAnx3UFzkLK7m8jHR4cco91Ld-20_YLjPgLpptK6jmKnsVSQt1749gVQm3sFFPPS3SrYQcZtMCbhomMt9ymG3kYFtl0FDdPpKQQymOKhcvZ_HYrgdS5J27KobLGQIRshk9wT204svn2JAI4C8O9VQ1fsf2SHiMBOhZwJ50H_Og1Vb-L2T2GQ7hK0p_3OtQqEDKRkgpuzbE8MqByu0BUMwwoc4lgLMOsGS-lStyGpN4GTsDktdMqMElY_VUuVpWhq-u6G_m9a3FKtXMzpO9Ci2NbSx788J4Ci7u8IHW96or8Fz_JQuYgTVKYJzPISlloFi6A8pYUUZhNSjl7MZdJrm6q_Kp85c1rvEsmF5PTxWnnKUZLZ786FlhpTrsCJ976NxWKlBhn35pyRvzAQpubx0-UsL2sqP_za7ydMX1472lGJhWVKY4L0pLb9y9kbSnvqHsDU9JQ2Q4lgGz1ub5nt4jubQCbJ0LwNbg_0gol8beFPONnjvGow7zJOgAB4Hqe_HjVZmrMO2tF6dVxT45YCqmDCO-rCPrdGGfrsUo4_8oc2g0dsPsSJvkD9ZPaOr6GEV8CGkPRSGRuZ44IuKpSTj69SX4CjKTrGlu75w_Yw2JMrp0zvighr2SPFzPXRV5qxNGawp2wUYEy42c-oSTkAcesChu4hzOZRASOsBS9ltSTwIrcvHFLV2mqzdZQrGMaq5cf93dEhSM3sUVgZshfJMJ9TH61bIF1MQEBVk5yY1yasypMFpkyAm90PQ2GDy42LZxnRuQDUizJ4oKQl8fUtPUVQjm74lvAbEGD5urvhUNYzBDYq1mkK2pdgR5I6DKcFjJk5cuzmP6TrVZj515LmTRjkDvSolNgDjv9T2_d81COlfPkUE7lJXPymcC6QsfD3H4J66823Vc6em355Mqf7uDRu0aqFWmJazHgco1-2AmQDLvhbbjqEdBsPj6xO7sVqXxVSQDSHW-iQygZUkRM09OQgBK7oNlV7c1uSy_Pt9dgokwGiAffqhkrlYgw7F-hxciodVd5td8CYl7ldJhPRK-BzdEOGuBVW9fCw3D7xxBiZfAQMEtOkFK35UQNfSB1L8Bj6ChA2CgSXCcgNmP8wPmtwidaUGZpOsaf65ksGIsaQXB95fG32BLeic7Z34HcL0WHmilGKRhHgbPHvRwSq0WI4aLJJe0sTb89FQxY3rh-hpRQM0OC1UCe4WdP_NR4AFjydPWhLMI0lm0-NewCkBlJok2M9cj6fAFWLqWB0vcmgar8YoT8gINvnaEyrCH5gZNA8k4ubdWxTCNPUNjsBXFTgJb-D6TkLOP-QvzNRIm6fXF8SnrpbkIlS9sgXcAy9qF7FxEJVUS8-QP3bckBJ8Km-WFr6S4rkk6tpyvz8L4i5ilYhpm5Re4DKFMX2ySirlotNPl86cnHuvFNNTjqNrE9_RmywPlw0zWOvfmLj8w8CJr1DOgsO6EY5sqh9D08EM9N21Eh_dBGqcL3XsM2dlAfovloTHnPkSYx-So7WAvLmosdZ-xifEusQ5UXyaHiBoEEzPseekfkhKc2FhMDZ8HOFhXDeWu5NdNNWqVMozuzA";

        // recaptchaAction: The action name corresponding to the token.
        String recaptchaAction = "login";

        // Unique ID of the customer, such as email, customer ID, etc.
        String userIdentifier = "bafang" + UUID.randomUUID().toString().split("-")[0];

        // Change this to a secret not shared with Google.
        final String HMAC_KEY = "BAFANG_HMAC_KEY";

        // Get instance of Mac object implementing HmacSHA256, and initialize it with the above
        // secret key.
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(HMAC_KEY.getBytes(StandardCharsets.UTF_8),
                "HmacSHA256"));
        byte[] hashBytes = mac.doFinal(userIdentifier.getBytes(StandardCharsets.UTF_8));
        ByteString hashedAccountId = ByteString.copyFrom(hashBytes);

        accountDefenderAssessment(projectId, recaptchaSiteKey, token, recaptchaAction, hashedAccountId);
    }

    /**
     * This assessment detects account takeovers. See,
     * https://cloud.google.com/recaptcha-enterprise/docs/account-takeovers The input is the hashed
     * account id. Result tells if the action represents an account takeover. You can optionally
     * trigger a Multi-Factor Authentication based on the result.
     */
    public static void accountDefenderAssessment(
            String projectId,
            String recaptchaSiteKey,
            String token,
            String recaptchaAction,
            ByteString hashedAccountId)
            throws IOException {
        try (RecaptchaEnterpriseServiceClient client = RecaptchaEnterpriseServiceClient.create()) {

            // Set the properties of the event to be tracked.
            Event event =
                    Event.newBuilder()
                            .setSiteKey(recaptchaSiteKey)
                            .setToken(token)
                            // Set the hashed account id (of the user).
                            // Recommended approach: HMAC SHA256 along with salt (or secret key).
                            .setHashedAccountId(hashedAccountId)
                            .build();

            // Build the assessment request.
            CreateAssessmentRequest createAssessmentRequest =
                    CreateAssessmentRequest.newBuilder()
                            .setParent(ProjectName.of(projectId).toString())
                            .setAssessment(Assessment.newBuilder().setEvent(event).build())
                            .build();

            Assessment response = client.createAssessment(createAssessmentRequest);

            // Check integrity of the response token.
            if (!checkTokenIntegrity(response.getTokenProperties(), recaptchaAction)) {
                return;
            }

            // Get the reason(s) and the reCAPTCHA risk score.
            // For more information on interpreting the assessment,
            // see: https://cloud.google.com/recaptcha-enterprise/docs/interpret-assessment
            for (ClassificationReason reason : response.getRiskAnalysis().getReasonsList()) {
                System.out.println(reason);
            }
            float recaptchaScore = response.getRiskAnalysis().getScore();
            System.out.println("The reCAPTCHA score is: " + recaptchaScore);
            String assessmentName = response.getName();
            System.out.println(
                    "Assessment name: " + assessmentName.substring(assessmentName.lastIndexOf("/") + 1));

            // Get the Account Defender result.
            com.google.recaptchaenterprise.v1.AccountDefenderAssessment accountDefenderAssessment =
                    response.getAccountDefenderAssessment();
            System.out.println(accountDefenderAssessment);

            // Get Account Defender label.
            List<AccountDefenderLabel> defenderResult =
                    response.getAccountDefenderAssessment().getLabelsList();
            // Based on the result, can you choose next steps.
            // If the 'defenderResult' field is empty, it indicates that Account Defender did not have
            // anything to add to the score.
            // Few result labels: ACCOUNT_DEFENDER_LABEL_UNSPECIFIED, PROFILE_MATCH,
            // SUSPICIOUS_LOGIN_ACTIVITY, SUSPICIOUS_ACCOUNT_CREATION, RELATED_ACCOUNTS_NUMBER_HIGH.
            // For more information on interpreting the assessment, see:
            // https://cloud.google.com/recaptcha-enterprise/docs/account-defender#interpret-assessment-details
            System.out.println("Account Defender Assessment Result: " + defenderResult);
        }
    }

    private static boolean checkTokenIntegrity(
            TokenProperties tokenProperties, String recaptchaAction) {
        // Check if the token is valid.
        if (!tokenProperties.getValid()) {
            System.out.println(
                    "The Account Defender Assessment call failed because the token was: "
                            + tokenProperties.getInvalidReason().name());
            return false;
        }

        // Check if the expected action was executed.
        if (!tokenProperties.getAction().equals(recaptchaAction)) {
            System.out.printf(
                    "The action attribute in the reCAPTCHA tag '%s' does not match "
                            + "the action '%s' you are expecting to score",
                    tokenProperties.getAction(), recaptchaAction);
            return false;
        }
        return true;
    }

}
